package de.rs.espresso.tools;

import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

public class Statistics {
	
	static long idCounter = 0;
	
	static ConcurrentHashMap<String, MeasurementResult> results = new ConcurrentHashMap<String, MeasurementResult>();
	
	static ConcurrentHashMap<Long, Measurement> running = new ConcurrentHashMap<Long, Measurement>();
	
	public synchronized static long startMeasurement(String name) {
		idCounter++;
		
		running.put(idCounter,new Measurement(name));		
		
		return idCounter;
		
	}
	
	public synchronized static void stopMeasurement(long measurementId) {
		
		Measurement m = running.get(measurementId);
		
		String name = m.getName();
		
		if(!results.containsKey(name)) {
			results.put(name, new MeasurementResult(name));
		}
		
		results.get(name).addMeasurement(m);
		
	}
	
	public synchronized static void printStatistics() {
		System.out.println("STATISTICS:");
		for(MeasurementResult m : results.values()) {
			System.out.println(m.toString());
		}
	}
	
	
	static private class Measurement {
		String name;
		long startedAt;
		
		Measurement(String name) {
			this.name = name;
			this.startedAt = System.currentTimeMillis();
		}

		public String getName() {
			return name;
		}

		public long getRuntime() {
			return System.currentTimeMillis()-startedAt;
		}
	}
	
	static private class MeasurementResult {
		
		String name;
		int runCount;
		
		ArrayList<Long> measurements = new ArrayList<Long>();
		
		public MeasurementResult(String name) {
			this.name = name;
			this.runCount = 0;
		}
		
		public void addMeasurement(Measurement m) {			
			long runTime = m.getRuntime();			
			measurements.add(runTime);			
			runCount++;
		}
		
		private long getAverageRuntime() {
			
			return getTotalRuntime()/runCount;
		}
		
		private long getTotalRuntime() {
			long total = 0;
			
			for(Long time : measurements) {
				total += time;
			}
			
			return total;
		}
		
		public String toString() {
			return name + "- Started " + runCount + " times, average runtime " + getAverageRuntime() + " ms, total runtime " + getTotalRuntime() +" ms";
		}
		
	}

}
